// Copyright (c) 2021 Presto Labs Pte. Ltd.
// Author: gekim

#pragma once

// std
#include <map>
#include <memory>
#include <regex>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>

// internal
#include "coin2/base/log.h"
#include "coin2/exchange/base/feed/processor.h"
#include "coin2/exchange/base/market/enums.h"
#include "coin2/exchange/kucoin_futures/feed_v1/update.h"
#include "coin2/flow/symbol_group.h"

namespace coin2::exchange::kucoin_futures::feed_v1 {
namespace impl {
using namespace std::string_literals;
using coin2::exchange::base::market::ExchangeType;
using coin2::exchange::base::market::MarketType;
using coin2::exchange::base::symbology::IProduct;
using coin2::exchange::base::feed::IFeedSubscriber;

struct KucoinFuturesChannel {
  std::string type;

  static KucoinFuturesChannel Parse(const std::string& ch) {
    std::string type_;
    if (ch == "level2") {
      return KucoinFuturesChannel{"book"};
    } else if (ch == "match") {
      return KucoinFuturesChannel{"trade"};
    } else if (ch == "mark.index.price") {
      return KucoinFuturesChannel{"instrument"};
    } else if (ch.find("/api/v1/contracts/active") != std::string::npos) {
      return KucoinFuturesChannel{"open_interest"};
    } else if (ch.find("/api/v1/funding-rate") != std::string::npos) {
      return KucoinFuturesChannel{"funding_rate"};
    } else if (ch.find("/api/v1/kline/query") != std::string::npos) {
      return KucoinFuturesChannel{"kline"};
    }
    return KucoinFuturesChannel{""};
  }
};

struct FeedTopicStat {
  bool snapshot_received = false;
  bool update_received = false;
};

class KucoinFuturesFeedProcessor : public coin2::exchange::base::feed::FeedParsingProcessor {
 public:
  explicit KucoinFuturesFeedProcessor(
      const std::string& system_name,
      const coin2::exchange::di::ConstantInjection& ci,
      const feed::RawParserConfig& config)
      : FeedParsingProcessor(
            system_name,
            MarketExchangeApi{MarketType::Futures, ExchangeType::Kucoin, "v1"},
            ci,
            config,
            "cc/coin2/exchange/kucoin_futures/feed_v1/schema.json") {}

  void OnTopicRecord(const base::executor::TopicRecordPacket& packet) override;

 private:
  std::unordered_map<std::string, std::set<std::string>> native_to_topics_;
  std::unordered_map<std::string, FeedTopicStat> topic_stat_;
  // 20221220T00:00:00
  static constexpr int64_t SNAPSHOT_ADDED_TS = 1'671'494'400'000'000'000LL;
};

}  // namespace impl
using impl::KucoinFuturesFeedProcessor;
}  // namespace coin2::exchange::kucoin_futures::feed_v1
